package ru.tulupov.collectionsbenchmark;

import java.lang.reflect.Method;
import java.util.List;

import org.apache.log4j.Logger;

import ru.tulupov.collectionsbenchmark.test.InitTestSuite;
import ru.tulupov.collectionsbenchmark.test.RandomDeletionTestSuite;
import ru.tulupov.collectionsbenchmark.test.RandomInsertionTestSuite;
import ru.tulupov.collectionsbenchmark.test.SequentalAccessTestSuite;
import ru.tulupov.collectionsbenchmark.test.RandomAccessTestSuite;
import ru.tulupov.collectionsbenchmark.test.SortTestSuite;
import ru.tulupov.collectionsbenchmark.util.Timer;
import ru.tulupov.collectionsbenchmark.util.Utils;

public class TestRunner {
	private static final Logger LOGGER = Logger.getLogger(TestRunner.class);

	public void start() {
		List<Class<?>> classes = Utils
				.getClassesForPackage("ru.tulupov.collectionsbenchmark.test");
		for (Class<?> clazz : classes) {
			runTestClass(clazz);
		}
	}

	private String getTestSuiteName(Class<?> clazz) {
		String name = clazz.getSimpleName();

		Test annotation = clazz.getAnnotation(Test.class);

		if (annotation != null && !annotation.name().equals("")) {
			name = annotation.name();
		}

		return name;
	}

	private void runTestClass(Class<?> clazz) {
		Statistic statistic = new Statistic();
		try {
			Object object = clazz.newInstance();
			for (Method method : clazz.getMethods()) {
				Test annotation = method.getAnnotation(Test.class);
				if (annotation != null) {
					String description = annotation.name();
					if (description.equals("")) {
						description = method.getName();
					}

					LOGGER.info(String.format("Starts running [%s] test case.",
							description));
					Timer timer = new Timer();
					timer.start();
					method.invoke(object);
					double time = timer.stop() / annotation.count();

					statistic.update(description, time);

					LOGGER.info(String
							.format("The test case [%s] is performed in %.09f seconds.",
									description, time));

				}

			}

			String message = String.format(
					"%s is the fastest in [%s] test suite.", statistic,
					getTestSuiteName(clazz));
			LOGGER.info(message);
			System.out.println(message);
		} catch (Exception e) {
			LOGGER.error("An error has occurred when invokes test case", e);
		}
	}
}
